#include "i2c.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_i2c.h"

// 初始化
void IIC1_Init(void)
{
    // 1.时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

    // 2.GPIO，PB6、PB7 复用开漏输出 MODE=11 CNF=11
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    // 3.I2C1配置
    // 硬件工作模式
    I2C_InitTypeDef I2C_InitStructure;
    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;                                // 标准I2C工作模式(相较于SMBus模式)
    I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;                        // 标准模式占空比
    I2C_InitStructure.I2C_OwnAddress1 = 0x00;
    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;                               // 使能自动应答
    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; // 使用7位地址
    I2C_InitStructure.I2C_ClockSpeed = 100000;                                // 总线时钟速度100kHz，对应标准模式速度
    I2C_Init(I2C1, &I2C_InitStructure);

    // 4.使能I2C1
    I2C_Cmd(I2C1, ENABLE);

    printf("IIC1 Init OK\r\n");
}

// 发送起始信号
uint8_t IIC1_Start(void)
{
    // 生成起始条件
    I2C_GenerateSTART(I2C1, ENABLE);

    // 等待起始条件生成完成
    uint32_t timeout = 0xffff;
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT) && timeout)
    {
        timeout--;
    }
    return timeout ? OK : EAIL;
}

// 设置发出停止信号
void IIC1_Stop(void)
{
    I2C_GenerateSTOP(I2C1, ENABLE);
}

// 主机发送设备地址并等待应答
uint8_t IIC1_SendAddr(uint8_t addr)
{
    // 发送地址
    I2C_Send7bitAddress(I2C1, addr, I2C_Direction_Transmitter);

    // 等待地址发送完成并被应答
    uint32_t timeout = 0xffff;
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) && timeout)
    {
        timeout--;
    }
    return timeout ? OK : EAIL;
}

// 主机发送一个字节数据并等待应答
uint8_t IIC1_SendByte(uint8_t byte)
{
    // 发送数据
    I2C_SendData(I2C1, byte);

    // 等待字节传输完成
    uint32_t timeout = 0xffff;
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED) && timeout)
    {
        timeout--;
    }
    return timeout ? OK : EAIL;
}

// 主机从从机读取一个字节数据
uint8_t IIC1_ReadByte(uint8_t ack)
{
    // 配置应答模式
    if (ack)
    {
        I2C_AcknowledgeConfig(I2C1, ENABLE);
    }
    else
    {
        I2C_AcknowledgeConfig(I2C1, DISABLE);
    }

    // 等待接收数据
    uint32_t timeout = 0xffff;
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED) && timeout)
    {
        timeout--;
    }
    // 返回接收到的数据
    return timeout ? I2C_ReceiveData(I2C1) : 0xFF;
}
